home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / DIRUTIL.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  9KB  |  397 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  * Rewritten for Turbo-C 2.0 routines by Phil Karn, KA9Q 25 March 89
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <dir.h>
  11. #include <dos.h>
  12. #include "global.h"
  13. #include "dirutil.h"
  14. #include "commands.h"
  15.  
  16. static void commas __ARGS((char *dest));
  17. static int fncmp __ARGS((char *a, char *b));
  18. static void format_fname_full __ARGS((FILE *file,struct ffblk *sbuf,int full,
  19.     int n));
  20. static void free_clist __ARGS((struct dirsort *this));
  21. static int getdir __ARGS((char *path,int full,FILE *file));
  22. static int getdir_nosort __ARGS((char *path,int full,FILE *file));
  23. static int nextname __ARGS((int command, char *name, struct ffblk *sbuf));
  24. static void print_free_space __ARGS((FILE *file,int n));
  25. static void undosify __ARGS((char *s));
  26. static char *wildcardize __ARGS((char *path));
  27.  
  28. #define REGFILE    (FA_HIDDEN|FA_SYSTEM|FA_DIREC)
  29.  
  30. #define    insert_ptr(list,new)    (new->next = list,list = new)
  31.  
  32. struct dirsort {
  33.     struct dirsort *next;
  34.     struct ffblk de;
  35. };
  36. #define    NULLSORT (struct dirsort *)0
  37.  
  38. /* Create a directory listing in a temp file and return the resulting file
  39.  * descriptor. If full == 1, give a full listing; else return just a list
  40.  * of names.
  41.  */
  42. FILE *
  43. dir(path,full)
  44. char *path;
  45. int full;
  46. {
  47.     FILE *fp;
  48.  
  49.     fp = tmpfile();
  50.     getdir(path,full,fp);
  51.     rewind(fp);
  52.     return fp;
  53. }
  54.  
  55. /* find the first or next file and lowercase it. */
  56. static int
  57. nextname(command, name, sbuf)
  58. int command;
  59. char *name;
  60. struct ffblk *sbuf;
  61. {
  62.     int found;
  63.  
  64.     switch(command){
  65.     case 0:
  66.         found = findfirst(name,sbuf,REGFILE);
  67.         break;
  68.     default:
  69.         found = findnext(sbuf);
  70.     }
  71.     found = found == 0;
  72.     if(found)
  73.         strlwr(sbuf->ff_name);
  74.  
  75.     return found;
  76. }
  77.  
  78. /* wildcard filename lookup */
  79. int
  80. filedir(name,times,ret_str)
  81. char *name;
  82. int times;
  83. char *ret_str;
  84. {
  85.     static struct ffblk sbuf;
  86.     int rval;
  87.  
  88.     switch(times){
  89.     case 0:
  90.         rval = findfirst(name,&sbuf,REGFILE);
  91.         break;
  92.     default:
  93.         rval = findnext(&sbuf);
  94.         break;
  95.     }
  96.     if(rval == -1){
  97.         ret_str[0] = '\0';
  98.     } else {
  99.         /* Copy result to output */
  100.         strcpy(ret_str, sbuf.ff_name);
  101.     }
  102.     return rval;
  103. }
  104. /* do a directory list to the stream 
  105.  * full = 0 -> short form, 1 is long
  106. */
  107. static int
  108. getdir(path,full,file)
  109. char *path;
  110. int full;
  111. FILE *file;
  112. {
  113.     struct ffblk sbuf;
  114.     int command = 0;
  115.     int n = 0;
  116.     struct dirsort *head, *here, *new;
  117.  
  118.     path = wildcardize(path);
  119.  
  120.     head = NULLSORT;    /* No head of chain yet... */
  121.     for(;;){
  122.         if (!nextname(command, path, &sbuf))
  123.             break;
  124.         command = 1;    /* Got first one already... */
  125.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  126.             continue;
  127.  
  128.         new = (struct dirsort *) malloc(sizeof(struct dirsort));
  129.         if(new == NULLSORT){
  130.             /* Clean up and call other routine */
  131.             free_clist(head);
  132.             return getdir_nosort(path,full,file);
  133.         }
  134.         new->de = sbuf;    /* Copy contents of directory entry struct */
  135.  
  136.         /* insert it into the list */
  137.         if (!head || fncmp(new->de.ff_name, head->de.ff_name) < 0) {
  138.             insert_ptr(head, new);
  139.         } else {
  140.             register struct dirsort *this;
  141.             for (this = head;
  142.                 this->next != NULLSORT;
  143.                 this = this->next)
  144.                 if (fncmp(new->de.ff_name, this->next->de.ff_name) < 0)
  145.                     break;
  146.             insert_ptr(this->next, new);
  147.         }
  148.     } /* infinite FOR loop */
  149.  
  150.     for (here = head; here; here = here->next)
  151.         format_fname_full(file,&here->de,full,++n);
  152.  
  153.     /* Give back all the memory we temporarily needed... */
  154.     free_clist(head);
  155.  
  156.     if(full)
  157.         print_free_space(file, n);
  158.  
  159.     return 0;
  160. }
  161. static int
  162. fncmp(a,b)
  163. register char *a, *b;
  164. {
  165.         int i;
  166.  
  167.     for(;;){
  168.         if (*a == '.')
  169.             return -1;
  170.         if (*b == '.')
  171.             return 1;
  172.         if ((i = *a - *b++) != 0)
  173.             return i;
  174.         if (!*a++)
  175.             return -1;
  176.     }
  177. }
  178. /* Change working directory */
  179. int
  180. docd(argc,argv,p)
  181. int argc;
  182. char *argv[];
  183. void *p;
  184. {
  185.     char dirname[128];
  186.  
  187.     if(argc > 1){
  188.         if(chdir(argv[1]) == -1){
  189.             printf("Can't change directory\n");
  190.             return 1;
  191.         }
  192.     }
  193.     if(getcwd(dirname,128) != NULLCHAR){
  194.         undosify(dirname);
  195.         printf("%s\n",dirname);
  196.     }
  197.     return 0;
  198. }
  199. /* List directory to console */
  200. int
  201. dodir(argc,argv,p)
  202. int argc;
  203. char *argv[];
  204. void *p;
  205. {
  206.     char *path;
  207.  
  208.     if(argc >= 2)
  209.         path = argv[1];
  210.     else
  211.         path = "*.*";
  212.  
  213.     getdir(path,1,stdout);
  214.     return 0;
  215. }
  216.  
  217.  
  218. /*
  219.  * Return a string with commas every 3 positions.
  220.  * If malloc() fails, return original string unmodified.
  221.  * else the original string is replace with the string with commas.
  222.  *
  223.  * The caller must be sure that there is enough room for the resultant
  224.  * string.
  225.  *
  226.  *
  227.  * k3mc 4 Dec 87
  228.  */
  229. static void
  230. commas(dest)
  231. char *dest;
  232. {
  233.     char *src, *core;    /* Place holder for malloc */
  234.     unsigned cc;        /* The comma counter */
  235.     unsigned len;
  236.  
  237.     len = strlen(dest);
  238.     /* Make a copy, so we can muck around */
  239.     if( (core = src = strdup(dest)) == NULLCHAR)
  240.         return;
  241.  
  242.     cc = (len-1)%3 + 1;    /* Tells us when to insert a comma */
  243.  
  244.     while(*src != '\0'){
  245.         *dest++ = *src++;
  246.         if( ((--cc) == 0) && *src ){
  247.             *dest++ = ','; cc = 3;
  248.         }
  249.     }
  250.     free(core);
  251.     *dest = '\0';
  252. }
  253. /* fix up the filename so that it contains the proper wildcard set */
  254. static char *
  255. wildcardize(path)
  256. char *path;
  257. {
  258.     struct ffblk sbuf;
  259.     static char ourpath[64];
  260.  
  261.     /* Root directory is a special case */
  262.     if(path == NULLCHAR ||
  263.        *path == '\0' ||
  264.        strcmp(path,"\\") == 0 ||
  265.        strcmp(path,"/") == 0)
  266.         path = "\\*.*";
  267.  
  268.     /* if they gave the name of a subdirectory, append \*.* to it */
  269.     if (nextname(0, path, &sbuf) &&
  270.         (sbuf.ff_attrib & FA_DIREC) &&
  271.         !nextname(1, path, &sbuf)) {
  272.  
  273.         /* if there isn't enough room, give up -- it's invalid anyway */
  274.         if (strlen(path) + 4 > 63) return path;
  275.         strcpy(ourpath, path);
  276.         strcat(ourpath, "\\*.*");
  277.         return ourpath;
  278.     }
  279.     return path;
  280. }
  281.  
  282. static void
  283. format_fname_full(file, sbuf, full, n)
  284. FILE *file;
  285. struct ffblk *sbuf;
  286. int full, n;
  287. {
  288.     char line_buf[50];        /* for long dirlist */
  289.     char cbuf[20];            /* for making line_buf */
  290.  
  291.     strcpy(cbuf,sbuf->ff_name);
  292.     if(sbuf->ff_attrib & FA_DIREC) strcat(cbuf, "/");
  293.     if (full) {
  294.         /* Long form, give other info too */
  295.         sprintf(line_buf,"%-13s",cbuf);
  296.         if(sbuf->ff_attrib & FA_DIREC)
  297.             strcat(line_buf,"           ");/* 11 spaces */
  298.         else {
  299.             sprintf(cbuf,"%ld",sbuf->ff_fsize);
  300.             commas(cbuf);
  301.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  302.         }
  303.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
  304.           (sbuf->ff_ftime >> 11) & 0x1f,    /* hour */
  305.           (sbuf->ff_ftime >> 5) & 0x3f,    /* minute */
  306.           (sbuf->ff_fdate >> 5) & 0xf,    /* month */
  307.           (sbuf->ff_fdate ) & 0x1f,        /* day */
  308.           (sbuf->ff_fdate >> 9) + 80,    /* year */
  309.           (n & 1) ? "   " : "\n");
  310.         fputs(line_buf,file);
  311.     } else {
  312.         fputs(cbuf,file);
  313.         fputs("\n",file);
  314.     }
  315. }
  316. /* Provide additional information only on DIR */
  317. static void
  318. print_free_space(file, n)
  319. FILE *file;
  320. int n;
  321. {
  322.     unsigned long free_bytes, total_bytes;
  323.     char s_free[11], s_total[11];
  324.     char cbuf[20];
  325.     struct dfree dtable;
  326.     unsigned long bpcl;
  327.  
  328.     if(n & 1)
  329.         fputs("\r\n",file);
  330.  
  331.     /* Find disk free space */
  332.     getdfree(0,&dtable);
  333.  
  334.     bpcl = dtable.df_bsec * dtable.df_sclus;
  335.     free_bytes  = dtable.df_avail * bpcl;
  336.     total_bytes = dtable.df_total * bpcl;
  337.  
  338.     sprintf(s_free,"%ld",free_bytes);
  339.     commas(s_free);
  340.     sprintf(s_total,"%ld",total_bytes);
  341.     commas(s_total);
  342.  
  343.     if(n)
  344.         sprintf(cbuf,"%d",n);
  345.     else
  346.         strcpy(cbuf,"No");
  347.  
  348.     fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
  349.         cbuf,(n==1? "":"s"),s_free,s_total);
  350. }
  351. static void
  352. free_clist(this)
  353. struct dirsort *this;
  354. {
  355.     struct dirsort *next;
  356.  
  357.     while (this != NULLSORT) {
  358.         next = this->next;
  359.         free(this);
  360.         this = next;
  361.     }
  362. }
  363. static int
  364. getdir_nosort(path,full,file)
  365. char *path;
  366. int full;
  367. FILE *file;
  368. {
  369.     struct ffblk sbuf;
  370.     int command;
  371.     int n = 0;    /* Number of directory entries */
  372.  
  373.     path = wildcardize(path);
  374.     command = 0;
  375.     while(nextname(command, path, &sbuf)){
  376.         command = 1;    /* Got first one already... */
  377.         if (sbuf.ff_name[0] == '.')    /* drop "." and ".." */
  378.             continue;
  379.         format_fname_full(file, &sbuf, full, ++n);
  380.     }
  381.     if(full)
  382.         print_free_space(file, n);
  383.     return 0;
  384. }
  385.  
  386. /* Translate those %$#@!! backslashes to proper form */
  387. static void
  388. undosify(s)
  389. char *s;
  390. {
  391.     while(*s != '\0'){
  392.         if(*s == '\\')
  393.             *s = '/';
  394.         s++;
  395.     }
  396. }
  397.